﻿using ORM.Applicaiton;
using ORM.Enum;
using ORM.Model;
using ORM.Parser.Design;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ORM.Util
{
    public class GlobalTransitionBuilder
    {
        private static string GlobalTransition_ConnectStringName = "GlobalTransition_ConnectionString";
        private static GlobalTransitionBuilder _GlobalTransitionBuilder = null;
        private static object GlobalTransitionBuilder_Lock = new object(); //锁同步
        private static List<Fastorm_Undo_Log> DBTransitionList;
        private static DBUtil dbutil = new DBUtil();
        public static GlobalTransitionBuilder GetInstance()
        {
            if (_GlobalTransitionBuilder == null)
            {
                lock (GlobalTransitionBuilder_Lock)
                {
                    if (_GlobalTransitionBuilder == null)
                    {
                        _GlobalTransitionBuilder = new GlobalTransitionBuilder();
                        DBTransitionList = dbutil.FindList<Fastorm_Undo_Log>("select * from Fastorm_Undo_Log", GlobalTransition_ConnectStringName);
                    }
                }
            }
            return _GlobalTransitionBuilder;
        }

        public void AddGlobalTransitin(string ConnectStringName,string MainID,string BranchID,string SQL)
        {
            BaseStatement BS = StatementFactory.CreateStatement(SQL);
            BS.ConnectStringName = ConnectStringName;
            BS.Parse(SQL);
            Fastorm_Undo_Log undo = new Fastorm_Undo_Log();
            undo.Status = (int)UndoStatus.Add;
            undo.CreateDate = DateTime.Now;
            undo.ModifyDate = DateTime.Now;
            undo.MainID = MainID;
            undo.BranchID = BranchID;
            undo.ConnectStringName = ConnectStringName;
            undo.Server = ConfigUtil.GetServer(ConnectStringName);
            JObject obj = new JObject();
            obj.Add("RedoSQL", SQL);
            obj.Add("UndoSQList", new JArray(BS.GetRollBackSQL()).ToString());
            undo.RollbackInfo = obj.ToString();
            dbutil.Insert<Fastorm_Undo_Log>(undo, GlobalTransition_ConnectStringName);
            DBTransitionList.Add(undo);
        }

        public void UpdateBranchStatus(string MainID, string BranchID,UndoStatus Status)
        {
            string sql = string.Format("update fastorm_undo_log set Status={0},ModifyDate='{1}' where MainID='{2}' and BranchID='{3}'", (int)Status,DateTime.Now.ToString(),MainID, BranchID);
            dbutil.ExecuteSQL(sql, GlobalTransition_ConnectStringName);
        }

        public void UpdateBranchStatus(string MainID, UndoStatus Status)
        {
            string sql = string.Format("update fastorm_undo_log set Status={0},ModifyDate='{1}' where MainID='{2}'", (int)Status,DateTime.Now.ToString(), MainID);
            dbutil.ExecuteSQL(sql, GlobalTransition_ConnectStringName);
        }

        public bool ExecuteRollBack(string MainID)
        {
            bool IsSuccess = true;
            //后执行的先复原
            DataTable dt = dbutil.FindView(string.Format("select * from fastorm_undo_log where MainID='{0}' order by id desc", MainID), GlobalTransition_ConnectStringName);
            foreach (DataRow item in dt.Rows)
            {
                Fastorm_Undo_Log undo = MapperBuilder.GetInstance().MapData2Entity<Fastorm_Undo_Log>(item);
                JObject rollbackinfo = JsonConvert.DeserializeObject<JObject>(undo.RollbackInfo);
                List<String> UndoSQList = JsonConvert.DeserializeObject<List<String>>(rollbackinfo.GetValue("UndoSQList").ToString());
                foreach (String undosql in UndoSQList)
                {
                    try
                    {
                        dbutil.ExecuteSQL(undosql,undo.ConnectStringName);
                        UpdateBranchStatus(undo.MainID, undo.BranchID, UndoStatus.SuccessUndo);
                    }
                    catch (System.Exception e)
                    {
                        UpdateBranchStatus(undo.MainID, undo.BranchID, UndoStatus.FailUndo);
                        IsSuccess = false;
                    }
                }
            }
            return IsSuccess;
        }
    }
}
